#include "GBufferRenderPass.h"
#include <SEngine/Render/RenderFeature/UtilRenderFeature.h>
#include <SEngine/Render/RenderFeature/ModelRenderFeature.h> 
#include <SEngine/Render/Descriptors/SceneDescriptor.h>
#include <SERender/Renderer/Renderer.h>
#include <SECore/Ecs/Scene.h>
#include <SEngine/Ecs/Components/ModelRenderComp.h>
#include <SERender/Descriptors/FrameDescriptor.h>
#include <SEForwardRenderPiplinePlugin/GBuffer.h>
#include <SEUi/Util/Util.h>
#include <SEUi/SEUi.h>

#include <SEForwardRenderPiplinePlugin/RenderTargetManager.h>
#include <SERender/Resourses/Loader/ShaderLoader.h>
#include <SEngine/Render/RenderFeature/UBORenderFeature.h>

namespace SEngine
{

    GBufferRenderPass::GBufferRenderPass(Renderer &renderer)
        : RenderPass(renderer)
    {
        m_gBufferShader = Manager::GetInstance().Get<Shader>("GBuffer").value();
        m_fbo = std::make_unique<FrameBuffer>();
    }

    void GBufferRenderPass::BeginFrame()
    {
    }

    void GBufferRenderPass::DrawFrame()
    {
        auto scene = m_renderer.AnyDescriptor::GetDescriptor<SceneDescriptor>()->get().scene;
        auto & rtManager = m_renderer.AnyDescriptor::GetDescriptor<RenderTargetManager>()->get();
        auto & frame = m_renderer.AnyDescriptor::GetDescriptor<FrameDescriptor>()->get();
        auto & utilFeature = m_renderer.Descriptor<RenderFeature>::GetDescriptor<UtilRenderFeature>()->get();
        auto & modelFeature = m_renderer.Descriptor<RenderFeature>::GetDescriptor<ModelRenderFeature>()->get();

        m_renderer.UseFrameBuffer(*m_fbo, [&]() {
            m_fbo->ClearAttachments();
            m_fbo->SwapAttachments(Attachment::COLOR_ATTACHMENT0, *rtManager.GetTarget("PositionRT"));
            m_fbo->SwapAttachments(Attachment::COLOR_ATTACHMENT1, *rtManager.GetTarget("NormalRT"));
            m_fbo->SwapAttachments(Attachment::COLOR_ATTACHMENT2, *rtManager.GetTarget("TangentRT"));
            m_fbo->SwapAttachments(Attachment::COLOR_ATTACHMENT3, *rtManager.GetTarget("DepthRT"));
            m_fbo->SwapAttachments(Attachment::COLOR_ATTACHMENT4, *rtManager.GetTarget("AlbedoRT"));
            m_fbo->EnableRenderBuffer(true);
            m_fbo->Resize(frame.w, frame.h);
            m_fbo->Use();
            // ResValue(m_gBufferShader).SetUniform("u_zFar", frame.camera.GetZFar());
            // ResValue(m_gBufferShader).SetUniform("u_zNear", frame.camera.GetZNear());
            m_renderer.GetDrive()->Clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT);
            scene->Components<ModelRenderComp>([&](Actor & actor, ModelRenderComp & comp) {
                modelFeature.DrawModel(comp.m_model, m_gBufferShader);
            });
        });

        // ShowRT("PositionRT", rtManager.GetTarget("PositionRT")->GetId());
        // ShowRT("NormalRT", rtManager.GetTarget("NormalRT")->GetId());
        // ShowRT("TangentRT", rtManager.GetTarget("TangentRT")->GetId());
        // ShowRT("DepthRT", rtManager.GetTarget("DepthRT")->GetId());
        // ShowRT("AlbedoRT", rtManager.GetTarget("AlbedoRT")->GetId());

        
        SignalUpdateUI.AddSlot([this]() {
            ImGui::PushID("GBufferRenderPass");
            if (ImGui::CollapsingHeader("GBufferRenderPass")) {
                if (ImGui::Button("Reload")) {
                    m_gBufferShader.Reload([](auto & path, auto & name) {
                        ShaderLoader loader;
                        return loader.Load(path).CreateShader(EngineUniformBlockBinder());
                    });
                }
            }
            ImGui::PopID();
            return SlotState::Once;
        });
    }

} // namespace SEngine
